package cn.lbd.auth.security;


import cn.lbd.auth.core.Common;
import cn.lbd.auth.model.Resource;
import cn.lbd.auth.entity.User;
import cn.lbd.auth.model.RoleAuth;
import cn.lbd.auth.service.AdminService;
import cn.lbd.auth.utils.JwtTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户登录认证信息查询
 *
 * @author fangliqing
 * @date 2021.1.7
 */
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private AdminService adminService;
    @Autowired
    private StringRedisTemplate template;

    @Override
    public UserDetails loadUserByUsername(String operatorId) throws UsernameNotFoundException {
        User user = adminService.selectOperatorByLoginName(operatorId);
        if (user == null) {
            throw new UsernameNotFoundException("该用户不存在");
        }

        Integer operatorRole = adminService.getOperatorRoleByOperId(Integer.parseInt(operatorId)).get(0).getRoleId();
        // 用户权限列表，根据用户拥有的权限标识与如 @PreAuthorize("hasAuthority('资源id')") 标注的接口对比，决定是否可以调用接口
        Set<String> permissions = new HashSet<>();
        Set<String> urls = new HashSet<>();
        for (RoleAuth roleAuth : adminService.getAuthByRoleId(operatorRole)) {
            Integer resourceId = roleAuth.getResourceId();
            Resource resource = adminService.getResourceByResId(resourceId);
            if (resource == null) {
                permissions.add(String.valueOf(resourceId));
            } else if (resource != null && resource.getSuperResourceId() == 0) {//说明是候选组apply或工作流用户，加他本身的id。工作流用
                permissions.add(resource.getResourceUrl());
            } else {
                permissions.add(String.valueOf(resourceId));
                if (resource != null && resource.getResourceUrl().contains("/") ) {
                    String[] split = resource.getResourceUrl().split("/");
                    if (split.length > 0 || split != null) {
                        urls.add("/"+split[1]);
                    }
                }
            }
        }
        String authKey = user.getOperatorId() + ":Auth";
        //将权限信息存在redis，以便网关层统一鉴权
        template.opsForValue().set(authKey
                , urls.toString()
                , Common.expire
                , TimeUnit.MILLISECONDS);
        log.info("向Redis写入认证信息：{}",authKey);
        List<GrantedAuthority> grantedAuthorities = permissions.stream().map(GrantedAuthorityImpl::new)
                .collect(Collectors.toList());
        return new JwtUserDetails(String.valueOf(user.getOperatorId()), user.getPassword(), grantedAuthorities);
    }
}
